# soundcontroller_win.py (数字键版)
import numpy as np
import sounddevice as sd
import ctypes
import threading
import time

# Windows API 声明
GetAsyncKeyState = ctypes.windll.user32.GetAsyncKeyState
KEY_EVENT = 0x8000  # 键盘事件标志

# 数字键到频率的映射
key_to_freq = {
    "7": 18500,
    "8": 18700,
    "9": 18900,
    "4": 19100,
    "6": 18600,
    "1": 18800,
    "2": 19000,
    "3": 19200,
}


class AudioPlayer:
    """音频播放管理器"""

    def __init__(self):
        self.active_frequencies = set()  # 存储当前激活的频率
        self.lock = threading.Lock()  # 线程锁

    def sound_creator(self, frequency, sample_rate=44100):
        """生成指定频率的正弦波（强制转换为 float32）"""
        duration = 0.1  # 单个音频块时长（秒）
        t = np.linspace(0, duration, int(sample_rate * duration), endpoint=False)
        wave = np.sin(2 * np.pi * frequency * t)  # 默认生成 float64
        return wave.astype(np.float32)  # 转换为 float32

    def audio_player(self, frequency):
        try:
            wave = self.sound_creator(frequency)
            stream = sd.OutputStream(samplerate=44100, channels=1, dtype="float32")
            with stream:
                while self.is_playing(frequency):
                    stream.write(wave)
        except Exception as e:
            print(f"音频播放错误: {str(e)}")

    def is_playing(self, frequency):
        """检查指定频率是否正在播放"""
        with self.lock:
            return frequency in self.active_frequencies

    def start_playback(self, frequency):
        """启动音频播放线程"""
        if not self.is_playing(frequency):
            with self.lock:
                self.active_frequencies.add(frequency)
            thread = threading.Thread(target=self.audio_player, args=(frequency,))
            thread.daemon = True
            thread.start()

    def stop_playback(self, frequency):
        """停止指定频率播放"""
        if self.is_playing(frequency):
            with self.lock:
                self.active_frequencies.discard(frequency)

    def scan_keys(self):
        """持续扫描数字小键盘按键状态"""
        # 数字小键盘虚拟键码 (Numpad keys)
        vk_codes = {
            "1": 0x61,  # VK_NUMPAD1
            "2": 0x62,  # VK_NUMPAD2
            "3": 0x63,  # VK_NUMPAD3
            "4": 0x64,  # VK_NUMPAD4
            "6": 0x66,  # VK_NUMPAD6
            "7": 0x67,  # VK_NUMPAD7
            "8": 0x68,  # VK_NUMPAD8
            "9": 0x69,  # VK_NUMPAD9
        }

        while True:
            for key, vk_code in vk_codes.items():
                if key in key_to_freq:  # 确保键在映射中
                    frequency = key_to_freq[key]
                    if GetAsyncKeyState(vk_code) & KEY_EVENT:  # 按下状态检测
                        self.start_playback(frequency)
                    else:
                        self.stop_playback(frequency)
            time.sleep(0.05)  # 控制扫描频率


def main():
    player = AudioPlayer()
    scan_thread = threading.Thread(target=player.scan_keys)
    scan_thread.daemon = True
    scan_thread.start()

    print("按住数字小键盘键(1,2,3,4,6,7,8,9)开始发声，松开停止...")
    try:
        while True:
            time.sleep(1)  # 主线程保持运行
    except KeyboardInterrupt:
        pass


if __name__ == "__main__":
    main()
